/*
 * Copyright (C) 2014 luke.
 * 
 * This file is part of Silvie.
 * 
 * Silvie is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 * 
 * Silvie is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 * 
 * You should have received a copy of the GNU General Public License
 * along with Silvie.  If not, see <http://www.gnu.org/licenses/>.
 */

package silvie.resources.chrmodel.chunks;

import java.util.ArrayList;
import java.util.List;

import javax.vecmath.Point3f;

import silvie.resources.chrmodel.structures.Polygon;
import utils.DataReader;

/**
 * AbstractChunk specialization for "shape" chunks. These chunks are contained
 * in the 0x7f03 model chunk and describe each shape that makes up the model.
 * 
 * @author luke
 */
public class Chunk0x7f02 extends AbstractChunk {
	public static final int POLYGON_VERTEX_INFO_SIZE = 16;
	private static final int VERTICES_OFFSET = 108;
	private static final int POLYGON_COUNT_OFFSET = 20;
	private static final int NORMAL_COUNT_OFFSET = 16;
	private static final int VERTEX_COUNT_OFFSET = 12;
	private static final int SHAPE_ID_OFFSET = 4;
	private int shapeId;
	private int vertexCount;
	private int faceNormalCount;
	private int polygonCount;
	private List<Point3f> vertices;
	private List<Point3f> faceNormals;
	private List<Polygon> polygons;

	/**
	 * Chunk0x7f02 constructor.
	 * 
	 * @see AbstractChunk#AbstractChunk(int, byte[])
	 */
	public Chunk0x7f02(int id, byte[] data) {
		super(id, data);
		this.shapeId = 0;
		this.vertexCount = 0;
		this.faceNormalCount = 0;
		this.vertices = new ArrayList<Point3f>();
		this.faceNormals = new ArrayList<Point3f>();
		this.polygons = new ArrayList<Polygon>();
	}

	@Override
	public int decode() {
		this.shapeId = DataReader.readInt(super.data, SHAPE_ID_OFFSET);
		this.vertexCount = DataReader.readInt(super.data, VERTEX_COUNT_OFFSET);
		this.faceNormalCount = DataReader.readInt(super.data, NORMAL_COUNT_OFFSET);
		this.polygonCount = DataReader.readInt(super.data, POLYGON_COUNT_OFFSET);
		for (int i = 0; i < this.vertexCount; i++) {
			this.vertices.add(DataReader.readPoint3f(super.data, VERTICES_OFFSET + i * 3 * DataReader.FLOAT_SIZE));
		}
		int position = VERTICES_OFFSET + this.vertexCount * 3 * DataReader.FLOAT_SIZE;
		for (int i = 0; i < this.faceNormalCount; i++) {
			Point3f normal = DataReader.readPoint3f(super.data, position + i * 3 * DataReader.FLOAT_SIZE);
			this.faceNormals.add(normal);
		}
		position += this.faceNormalCount * 3 * DataReader.FLOAT_SIZE;
		for (int i = 0; i < this.polygonCount; i++) {
			// Skip 2 chars
			position += 2;
			int polygonVertexCount = DataReader.readChar(super.data, position++);
			int textureOffsetIndex = DataReader.readChar(super.data, position++);
			// Skip 4 chars
			position += 4;
			int polygonDataSize = polygonVertexCount * POLYGON_VERTEX_INFO_SIZE;
			byte[] polygonData = new byte[polygonDataSize];
			System.arraycopy(super.data, position, polygonData, 0, polygonDataSize);
			position += polygonDataSize;
			Polygon polygon = new Polygon(polygonData, polygonVertexCount, textureOffsetIndex);
			this.polygons.add(polygon);
		}
		return super.data.length;
	}

	/**
	 * Decodes each polygon in this shape chunk.
	 */
	public void decodePolygons() {
		for (Polygon polygon : this.polygons) {
			polygon.decode();
		}
	}

	public List<Polygon> getPolygons() {
		return this.polygons;
	}

	public List<Point3f> getVertices() {
		return this.vertices;
	}

	public int getShapeId() {
		return this.shapeId;
	}
}
